import 'dart:convert';
import 'dart:io';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_keep_book/core/network/http_url.dart';
import 'package:flutter_keep_book/core/utils/m_logs.dart';
import 'package:package_info/package_info.dart';
import 'package:wifi_info_plugin_plus/wifi_info_plugin_plus.dart';

import '../../app/provider/user_provider.dart';
import '../natives/natives.dart';
import '../storage/local_storage.dart';
import 'error_code.dart';
import 'network.dart';


/// 平台标识。如：magicbox_ios magicbox_android
final String kPlatformKey = 'magicbox_${Platform.operatingSystem}';

/// 接口请求。
class Api {
  Api._() {
    _httpManager = HttpManager(
      baseUrl: HttpUrl.baseUrl,
      headersProvider: () {
        final headers = <String, dynamic>{
          'Accept': 'application/json',
          'storeId': 10001,
          'platform': kPlatformKey,
        };

        final token = LocalStorage.token;
        if (token != null && token.isNotEmpty) {
          headers['Authorization'] = token;
        }

        return headers;
      },
    );
  }

  static final shared = Api._();

  late HttpManager _httpManager;

  static String? get osVersion => shared._cacheOSVersion;

  /// 设置/更新代理。
  static void setProxy(Map<String, String>? networkProxy) => shared._httpManager.setProxy(networkProxy);

  static Future<NetworkResult> request({
    String? baseUrl,
    required String path,
    HttpMethod method = HttpMethod.get,
    Map<String, dynamic>? params,
    bool withLoading = false,
  }) async {
    // mprint('请求 => $path');
    if (withLoading) {
      EasyLoading.show(maskType: EasyLoadingMaskType.clear);
    }

    final totalParams = <String, dynamic>{};
    if (params != null && params.isNotEmpty) {
      totalParams.addAll(params);
    }

    final extraParams = await shared.getExtraParams();
    totalParams.addAll(extraParams);

    final result = await shared._httpManager.request(
      baseUrl: baseUrl,
      path: path,
      method: method,
      params: totalParams,
    );

    if (result.isFailed) {
      extraParams['request_url'] = baseUrl ?? HttpUrl.baseUrl;
      extraParams['request_path'] = path;
      // 登录失效
      switch (result.code) {
        case ErrorCode.tokenInvalid:
        case ErrorCode.shouldLogin:
        case ErrorCode.logout:
          await UserProvider.shared.logout();
          break;
        default:
          break;
      }
    }

    if (withLoading) {
      EasyLoading.dismiss();
    }

    return result;
  }

  /// GET 请求。
  static Future<NetworkResult> requestGet({
    String? basePath,
    required String path,
    Map<String, dynamic>? param,
    bool withLoading = false,
  }) =>
      request(
        baseUrl: basePath,
        path: path,
        method: HttpMethod.get,
        params: param,
        withLoading: withLoading,
      );

  /// POST 请求。
  static Future<NetworkResult> requestPost({
    String? basePath,
    required String path,
    Map<String, dynamic>? param,
    bool withLoading = false,
    bool isShowErrorToast = false,
  }) =>
      request(
        baseUrl: basePath,
        path: path,
        method: HttpMethod.post,
        params: param,
        withLoading: withLoading,
      );

  /// 解析参数并发起请求。
  ///
  /// 弹窗的跳转类型可配置为 [JumpType.api] 请求接口。
  ///
  /// [params] 为弹窗配置的接口请求参数。
  static Future<NetworkResult> parseAndRequest({
    required Uri uri,
    required Map<String, dynamic>? params,
    String requestType = 'GET',
    bool withLoading = false,
  }) async {
    final host = '${uri.scheme}://${uri.host}';
    final path = uri.path;

    return request(
      baseUrl: host,
      path: path,
      method: (requestType == 'POST' || requestType == 'post') ? HttpMethod.post : HttpMethod.get,
      params: params,
      withLoading: withLoading,
    );
  }

  String? _cacheAppVersion;
  String? _cachePhoneModel;
  String? _cacheOSVersion;
  String? _cacheChannel;
  String _cacheOaid = '';
  int? _cacheIsInstalledPregnancyApp;

  /// iOS IDFA
  String? _cacheIDFA;

  /// 推送 CID
  String _cid = '';

  int osAndroidSDKVersion = 0;

  /// mac
  String androidMac = '';
}

extension ApiParams on Api {
  /// 每个接口的固定参数。
  /// 这个不放在 [HttpManager] 的初始化参数里面是因为在接口失败的时候，需要将这些参数上报Bugly。
  Future<Map<String, dynamic>> getExtraParams() async {
    final params = <String, dynamic>{};
    // params['t'] = DateTime.now().millisecondsSinceEpoch ~/ 1000;
    // params['appkey'] = kPlatformKey;
    // params['user_id'] = UserProvider.userId;
    // params['version'] = await getAppVersion();
    // params['channel'] = await getChannel();

    // 敏感数据，加密
    // params['params'] = await getSensitiveParamsWithAesEncrypt();
    return params;
  }

  /// 对敏感参数进行加密
  Future<String> getSensitiveParamsWithAesEncrypt() async {
    final params = <String, dynamic>{};

    // ！[getSystemInfoParams] 需要放在最前面 ！
    final systemInfo = await getSystemInfoParams();
    if (systemInfo != null && systemInfo.isNotEmpty) {
      params.addAll(systemInfo);
    }

    params['source'] = kPlatformKey;
    params['channel'] = await getChannel();
    params['openid'] = await getOaid();
    params['getui_cid'] = await getCid();
    params['installed_pregnancy_app'] = await isInstalledPregnancyApp();
    params['idfa'] = await getIDFA();

    // !! 需要先调用 [getSystemInfoParams] 再调用 [getMac]
    params['mac'] = await getMac();
    String jsonParams = jsonEncode(params);
    return jsonParams;
  }

  Future<String> getAppVersion() async {
    if (_cacheAppVersion == null) {
      PackageInfo packageInfo = await PackageInfo.fromPlatform();
      _cacheAppVersion = packageInfo.version;
    }

    return _cacheAppVersion!;
  }

  Future<String> getOaid() async {
    if (isDesktop || !LocalStorage.isAgreePrivacy) {
      return '';
    }
    if (_cacheOaid.isEmpty) {
      _cacheOaid = await Natives.getOaid();
    }
    MLogs.info("flutter获取oaid-----$_cacheOaid");
    return _cacheOaid;
  }

  /// 获取设备渠道号
  Future<String> getChannel() async {
    if (_cacheChannel == null) {
      if (Platform.isIOS) {
        _cacheChannel = 'App_Store';
      } else if (Platform.isAndroid) {
        _cacheChannel = await Natives.getChannel() ?? 'normal';
      } else {
        _cacheChannel = Platform.operatingSystem;
      }
    }

    return _cacheChannel!;
  }

  /// 获取设备信息
  Future<Map<String, dynamic>?> getSystemInfoParams() async {
    if (isDesktop) {
      return null;
    }
    if (!LocalStorage.isAgreePrivacy) {
      return null;
    }
    if (_cachePhoneModel == null) {
      DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin();
      if (Platform.isIOS) {
        final info = await deviceInfoPlugin.iosInfo;
        _cachePhoneModel = info.utsname.machine ?? info.model;
        _cacheOSVersion = info.systemVersion;
      } else if (Platform.isAndroid) {
        final info = await deviceInfoPlugin.androidInfo;
        _cachePhoneModel = info.model;
        _cacheOSVersion = info.version.release;
        osAndroidSDKVersion = info.version.sdkInt;
      } else {
        _cachePhoneModel = Platform.operatingSystem;
        _cacheOSVersion = Platform.operatingSystemVersion;
      }
    }

    return <String, dynamic>{
      'model': _cachePhoneModel ?? '',
      'os_version': _cacheOSVersion ?? '',
    };
  }

  Future<String?> getPhoneModel() async {
    if (_cachePhoneModel == null) {
      await getSystemInfoParams();
    }
    return _cachePhoneModel;
  }

  /// 是否有安装孕育 app。
  Future<int> isInstalledPregnancyApp() async {
    if (_cacheIsInstalledPregnancyApp == null) {
      if (Platform.isIOS) {
        _cacheIsInstalledPregnancyApp = await Natives.isInstalledPregnancyApp() ?? 0;
      } else {
        _cacheIsInstalledPregnancyApp = 0;
      }
    }

    return _cacheIsInstalledPregnancyApp!;
  }

  /// 获取 iOS IDFA
  Future<String> getIDFA() async {
    const none = '00000000-0000-0000-0000-000000000000';

    if (!Platform.isIOS || !LocalStorage.isAgreePrivacy) {
      return none;
    }
    _cacheIDFA ??= await Natives.getIDFA() ?? none;
    return _cacheIDFA!;
  }

  Future<String> getCid() async {
    if (isDesktop) {
      return '';
    }
    return _cid;
  }

  Future<String> getMac() async {
    if (!LocalStorage.isAgreePrivacy || !Platform.isAndroid) {
      return '';
    }
    if(true){
      //mac 默认拿不到
      return "";
    }
    if (androidMac.isEmpty && osAndroidSDKVersion < 29) {
      final wifiInfo = await WifiInfoPlugin.wifiDetails;
      androidMac = wifiInfo != null ? wifiInfo.macAddress.toString() : '...';
      _cacheOaid = androidMac;
    }
    return androidMac;
  }

  /// 是否桌面端
  bool get isDesktop => Platform.isMacOS || Platform.isWindows;
}
